package com.lfz.demo.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lfz.demo.common.enums.LogType;
import com.lfz.demo.common.enums.MenuType;
import com.lfz.demo.common.target.HoneyLogs;
import com.lfz.demo.entity.User;
import com.lfz.demo.service.SmsService;
import com.lfz.demo.service.UserService;
import com.lfz.demo.vo.DataView;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author lfz
 * @date 2025/3/3 9:23
 */

@RestController
@RequestMapping("/login")
public class LoginController {

    private static final Logger logger = LoggerFactory.getLogger(FindPwdController.class);

    @Autowired
    private UserService userService;
    @Autowired
    private SmsService smsService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate; // 新增Redis依赖

    // 新增：校验手机号是否已注册
    @PostMapping("/checkPhone")
    public DataView checkPhone(@RequestParam String phone) {
        DataView dataView = new DataView();
        try {
            User user = userService.getOne(new QueryWrapper<User>().eq("phone", phone));
            if (user != null) {
                dataView.setCode(200);
                dataView.setMsg("手机号已注册");
            } else {
                dataView.setCode(101);
                dataView.setMsg("该手机号未注册，请先注册");
            }
        } catch (Exception e) {
            logger.error("校验手机号失败，手机号：{}", phone, e);
            dataView.setCode(500);
            dataView.setMsg("校验手机号失败，请稍后重试");
        }
        return dataView;
    }

    /**
     * 新增：发送手机验证码接口
     * @param phone
     * @return
     */
    @PostMapping("/sendCode")
    @HoneyLogs(operation = "发送手机验证码", type = LogType.LOGIN, menu = MenuType.UnFind)
    public DataView sendCode(@RequestParam String phone) {
        DataView dataView = new DataView();
        try {
            // 生成6位数字验证码
            String code = RandomUtil.randomNumbers(6);
            // 模拟发送短信
            smsService.sendSms(phone, "验证码：" + code);
            // 存储到Redis，有效期5分钟
            redisTemplate.opsForValue().set("sms:login:" + phone, code, 5, TimeUnit.MINUTES);
            dataView.setCode(200);
            dataView.setMsg("验证码已发送，有效期5分钟");
        } catch (Exception e) {
            logger.error("发送验证码失败，手机号：{}", phone, e);
            dataView.setCode(500);
            dataView.setMsg("发送验证码失败，请稍后重试");
        }
        return dataView;
    }

    /**
     * 验证码的逻辑
     * @param response
     * @param session
     * @throws IOException
     */
    @GetMapping("/getCode")
    public void getCode(HttpServletResponse response, HttpSession session) throws IOException {
        // 1、获取验证码对象(HuTool定义图形验证码的长,宽,验证码的位数（codeCount）,干扰线的条数（circleCount）)
        CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(116, 36, 4, 10);
        // 2、放入到session
        session.setAttribute("code", captcha.getCode());
        // 3、输出验证码
        ServletOutputStream outputStream = response.getOutputStream();
        captcha.write(outputStream);
        // 4、关闭输出流
        outputStream.close();
    };

    /**
     * 具体登录逻辑
     */
    @PostMapping("/login")
    @HoneyLogs(operation = "登录", type = LogType.LOGIN, menu = MenuType.UnFind)
    public DataView login(
            @RequestParam(required = false) String username,
            @RequestParam(required = false) String password,
            @RequestParam(required = false) String code, // 图形验证码（用户名登录用）
            @RequestParam(required = false) String phone, // 手机登录用
            @RequestParam(required = false) String verifyCode, // 手机验证码
            HttpSession session) {
        DataView dataView = new DataView();

        // 判断登录方式：用户名密码登录 or 手机验证码登录
        if (username != null && password != null) {
            // 用户名密码登录逻辑（原有逻辑）
            String sessionCode = (String) session.getAttribute("code");
            if (!sessionCode.equals(code)) {
                dataView.setCode(100);
                dataView.setMsg("图形验证码错误");
                return dataView;
            }
            // 执行Shiro登录
            try {
                Subject subject = SecurityUtils.getSubject();
                subject.login(new UsernamePasswordToken(username, password));
                User user = (User) subject.getPrincipal();
                if (user != null) {
                    dataView.setCode(200);
                    dataView.setMsg("登录成功");
                    session.setAttribute("user", user);
                } else {
                    dataView.setCode(100);
                    dataView.setMsg("用户名或密码错误");
                }
            } catch (Exception e) {
                logger.error("用户名密码登录失败，用户名：{}", username, e);
                dataView.setCode(100);
                dataView.setMsg("用户名或密码错误");
            }
        } else if (phone != null && verifyCode != null) {
            // 手机验证码登录逻辑
            String cachedCode = redisTemplate.opsForValue().get("sms:login:" + phone);
            if (StringUtils.isBlank(cachedCode) || !cachedCode.equals(verifyCode)) {
                dataView.setCode(101); // 自定义手机验证码错误码
                dataView.setMsg("短信验证码错误或过期");
                return dataView;
            }
            // 根据手机号查询用户
            User user = userService.getOne(new QueryWrapper<User>().eq("phone", phone));
            if (user == null) {
                dataView.setCode(101);
                dataView.setMsg("该手机号未注册, 请先注册！");
                return dataView;
            }
            // 执行Shiro登录（使用手机号作为用户名）
            // 手机验证码登录逻辑（关键修改：使用用户真实密码而非空密码）
            try {
                // 根据手机号查询用户（已通过验证码校验）
                user = userService.getOne(new QueryWrapper<User>().eq("phone", phone));
                // 获取用户真实密码
                String userPassword = user.getPassword();
                // 传递手机号和真实密码进行Shiro认证
                Subject subject = SecurityUtils.getSubject();
                subject.login(new UsernamePasswordToken(phone, userPassword)); // 不再传递空密码
                session.setAttribute("user", user);
                dataView.setCode(200);
                dataView.setMsg("登录成功");
            } catch (Exception e) {
                logger.error("手机验证码登录失败，手机号：{}", phone, e);
                dataView.setCode(101);
                dataView.setMsg("登录失败，请稍后重试");
            }
        } else {
            dataView.setCode(100);
            dataView.setMsg("登录参数错误");
        }

        return dataView;
    }


}


